package com.example.gpstest.activity;

import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
import android.location.GpsSatellite;
import android.location.GpsStatus;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.os.SystemClock;
import android.provider.Settings;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

import androidx.annotation.RequiresApi;
import androidx.appcompat.app.AppCompatActivity;

import com.bin.david.form.core.SmartTable;
import com.example.gpstest.DataBean.DataSearchStarBean;
import com.example.gpstest.DataBean.DataTestBean;
import com.example.gpstest.DataBean.GPSSharedPreference;
import com.example.gpstest.R;
import com.example.gpstest.Utils.ExcelUtil;
import com.example.gpstest.Utils.GPSConst;
import com.example.gpstest.Utils.LocationUtils;
import com.example.gpstest.Utils.ParametersPackage;
import com.lxj.xpopup.XPopup;
import com.lxj.xpopup.interfaces.OnInputConfirmListener;

import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;

import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;

public class GpsTtffActivity extends AppCompatActivity {
    @BindView(R.id.btn_cold)
    Button btnCold;
    @BindView(R.id.btn_warm)
    Button btnWarm;
    @BindView(R.id.btn_stop)
    Button btnStop;
    @BindView(R.id.btn_derive_ttff)
    Button btnDeriveTtff;
    @BindView(R.id.smartTableTtff)
    SmartTable smartTableTtff;
    @BindView(R.id.et_minsnr)
    EditText etMinsnr;
    @BindView(R.id.et_maxsnr)
    EditText etMaxsnr;
    @BindView(R.id.btn_derive_satellite)
    Button btnDeriveSatellite;
    @BindView(R.id.smartTable_satellite)
    SmartTable smartTableSatellite;
    @BindView(R.id.tv_positioning_failed)
    TextView tvPositioningFailed;
    @BindView(R.id.tv_runtimes)
    TextView tvRuntimes;


    private LocationManager locationManagerTTFF;
    private long longtime, betweenTime;
    private long startTime=0;
    private long endTime=0;
    private long runTimes=0;
    int countnumber = 0;
    int faileNum=0;
    private static float STAR_MAX_SNR = 0;//搜星最大有效snr 上限
    private static float STAR_MIN_SNR = 0;//最低有效snr 下限
    private List<DataTestBean> dataTestBeanList = new ArrayList<>();
    private List<DataSearchStarBean> dataStarBean = new ArrayList<>();
    private List<DataSearchStarBean> dataStarBean1 = new ArrayList<>();
    private List<DataTestBean> dataList = new ArrayList<>();
    private boolean bSnr;

    public double trueLatitude = 0.0d;
    public double trueLongitude = 0.0d;
    public double latitude = 0.0d;
    public double longitude = 0.0d;
    public double altitude = 0.0d;
    public double TTFF = 0.0d;
    public ParametersPackage mParametersPkg;
    private String status="";
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_gps_ttff);
        ButterKnife.bind(this);
        if (locationManagerTTFF == null) {
            locationManagerTTFF = (LocationManager) getSystemService(LOCATION_SERVICE);
        }
        mParametersPkg = new ParametersPackage();
    }

    @Override
    protected void onResume() {
        super.onResume();
        getInitialValue();
    }

    @OnClick({R.id.btn_cold, R.id.btn_warm, R.id.btn_stop, R.id.btn_derive_ttff, R.id.btn_derive_satellite})
    public void onViewClicked(View view) {
        String etMaxsnrStr = etMaxsnr.getText().toString();
        String etMinsnrStr = etMinsnr.getText().toString();
        switch (view.getId()) {
            case R.id.btn_cold:
                //参数设置
                Intent intent1 = new Intent(GpsTtffActivity.this, ParameterSetActivity.class);
                startActivity(intent1);
                break;
            case R.id.btn_warm:
                //每次启动清除表格数据
                clearDataList();
                clearMessageQueue();
                //间隔时间
                betweenTime = mParametersPkg.timeSpan * 1000;
                STAR_MAX_SNR = Float.valueOf(etMaxsnrStr);
                STAR_MIN_SNR = Float.valueOf(etMinsnrStr);
                btnCold.setEnabled(false);
                btnWarm.setEnabled(false);

                startLocation();
                break;
            case R.id.btn_stop:
                clearMessageQueue();
                btnCold.setEnabled(true);
                btnWarm.setEnabled(true);


                stopGPSListener();
                break;
            case R.id.btn_derive_ttff:
                new XPopup.Builder(this)
                        .asInputConfirm("保存", "默认保存的路径地址:/storage/emulated/0/GPSTestFile/", "ttff.xls", null,
                                new OnInputConfirmListener() {
                                    @Override
                                    public void onConfirm(String text) {
                                        if (text.contains(".xls")) {
                                            getExcelTTFF(text);
                                        } else {
                                            ExcelUtil.ShortToast(GpsTtffActivity.this, "保存失败，后缀名不是xls文件格式");
                                        }

                                    }
                                })
                        .show();

                break;
            case R.id.btn_derive_satellite:
                new XPopup.Builder(this)
                        .asInputConfirm("保存", "默认保存的路径地址:/storage/emulated/0/GPSTestFile/", "Satellite.xls", null,
                                new OnInputConfirmListener() {
                                    @Override
                                    public void onConfirm(String text) {
                                        if (text.contains(".xls")) {
                                            getExcelSatellite(text);
                                        } else {
                                            ExcelUtil.ShortToast(GpsTtffActivity.this, "保存失败，不是xls文件格式");
                                            return;
                                        }
                                    }
                                })
                        .show();
                break;
        }
    }

    @SuppressLint("MissingPermission")
    private void startLocation() {
        //判断GPS是否正常启动
        if (!locationManagerTTFF.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
            Toast.makeText(this, "请开启GPS导航", Toast.LENGTH_SHORT).show();
            //返回开启GPS导航设置界面
            Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
            startActivityForResult(intent, 0);
            return;
        }
        Bundle bundle = new Bundle();
        if (mParametersPkg.fixMode == 0) {
            bundle.putBoolean(GPSConst.GPS_CMD_ALL, true);
            boolean b =locationManagerTTFF.sendExtraCommand(LocationManager.GPS_PROVIDER, "delete_aiding_data", bundle);
            if (b){
                status="Cold";
            }
        } else if (mParametersPkg.fixMode == 1) {
            boolean b = locationManagerTTFF.sendExtraCommand(LocationManager.GPS_PROVIDER,
                    "delete_aiding_data", getBundle());
            if (b){
                status="Warm";
            }
        }
        startTime=System.currentTimeMillis();//开始时间
        longtime = SystemClock.elapsedRealtime();
        //1000位最小的时间间隔，1为最小位移变化；也就是说每隔5000ms会回调一次位置信息
        locationManagerTTFF.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 0, locationListener);
        //添加卫星状态改变监听
        locationManagerTTFF.addGpsStatusListener(gpsStatusListener);
        mHandler.sendEmptyMessageDelayed(2, mParametersPkg.ttff * 1000);
    }

    //停止gps监听
    public void stopGPSListener() {
        if (locationManagerTTFF != null) {
            locationManagerTTFF.removeUpdates(locationListener);
            locationManagerTTFF.removeGpsStatusListener(gpsStatusListener);
            endTime=System.currentTimeMillis();//结束时间
            runTimes+=endTime-startTime;
            tvRuntimes.setText(runTimes+"");
        }
    }


    private Handler mHandler = new Handler() {
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case 1:
                    startLocation();
                    return;
                case 2:
                    stopTTFFTime();
                    return;
                default:
                    return;
            }
        }
    };

    private void clearMessageQueue() {
        if (this.mHandler.hasMessages(1)) {
            this.mHandler.removeMessages(1);
        }
        if (this.mHandler.hasMessages(2)) {
            this.mHandler.removeMessages(2);
        }
    }

    LocationListener locationListener = new LocationListener() {
        @RequiresApi(api = Build.VERSION_CODES.O)
        @Override
        public void onLocationChanged(Location location) {
            bSnr = true;
            //清除消息2
            mHandler.removeMessages(2);
            long time = SystemClock.elapsedRealtime();
            latitude = location.getLatitude();
            longitude = location.getLongitude();
            altitude = location.getAltitude();
            TTFF = (double) (time - longtime);
            countnumber++;
            double cep = LocationUtils.getCep(latitude, longitude, trueLatitude, trueLongitude);
            stopGPSListener();
            dataList.add(new DataTestBean(cep, TTFF));
            updateTTFFAndCEPS(dataList.size());

            if (countnumber < mParametersPkg.testTime) {
                mHandler.sendEmptyMessageDelayed(1, betweenTime);
            } else {
                btnCold.setEnabled(true);
                btnWarm.setEnabled(true);
            }
        }

        @Override
        public void onStatusChanged(String provider, int status, Bundle extras) {

        }

        @Override
        public void onProviderEnabled(String provider) {

        }

        @Override
        public void onProviderDisabled(String provider) {

        }
    };

    //定位时间超时结束
    public void stopTTFFTime() {
        stopGPSListener();
        faileNum+=1;
        countnumber++;
        TTFF = -1.0d;
        dataTestBeanList.add(new DataTestBean(countnumber, 0.0d + "", 0.0d + "", 0.0d + "",-1.0d, -1.0d, TTFF, TTFF, TTFF, status, "失败"));
        smartTableTtff.setData(dataTestBeanList);
        tvPositioningFailed.setText(faileNum+"");
        if (countnumber < mParametersPkg.testTime) {
            mHandler.sendEmptyMessageDelayed(1, betweenTime);
        } else {
            btnCold.setEnabled(true);
            btnWarm.setEnabled(true);
        }
    }

    private GpsStatus.Listener gpsStatusListener = new GpsStatus.Listener() {
        @Override
        public void onGpsStatusChanged(int event) {
            switch (event) {
                //卫星状态改变
                case GpsStatus.GPS_EVENT_SATELLITE_STATUS:
                    dataStarBean.clear();
                    //获取当前状态
                    @SuppressLint("MissingPermission") GpsStatus gpsStatus = locationManagerTTFF.getGpsStatus(null);
                    //获取卫星颗数的默认最大值
                    int maxSatellites = gpsStatus.getMaxSatellites();
                    //获取所有的卫星
                    Iterator<GpsSatellite> iters = gpsStatus.getSatellites().iterator();
                    //卫星颗数统计
                    int count = 0;
                    int countnum = 0;
                    StringBuilder sb = new StringBuilder();
                    while (iters.hasNext() && count <= maxSatellites) {
                        count++;
                        GpsSatellite s = iters.next();
                        //卫星的信噪比
                        float snr = s.getSnr();
                        if (snr <= STAR_MAX_SNR && snr >= STAR_MIN_SNR && STAR_MAX_SNR > STAR_MIN_SNR) {
                            if (s.getPrn() <= 64 || (s.getPrn() >= 120 && s.getPrn() <= 138)) {
                                dataStarBean.add(new DataSearchStarBean(s.getPrn(), "GPS", snr, countnumber + ""));
                            } else if (s.getPrn() >= 201 && s.getPrn() <= 261) {
                                dataStarBean.add(new DataSearchStarBean(s.getPrn(), "BEIDOU", snr, countnumber + ""));
                            } else if (s.getPrn() >= 65 && s.getPrn() <= 88) {
                                dataStarBean.add(new DataSearchStarBean(s.getPrn(), "Glonass", snr, countnumber + ""));
                            } else if (s.getPrn() >= 301 && s.getPrn() <= 336) {
                                dataStarBean.add(new DataSearchStarBean(s.getPrn(), "Galileo", snr, countnumber + ""));
                            }
                        } else if (STAR_MAX_SNR == STAR_MIN_SNR) {
                            if (s.getPrn() <= 64 || (s.getPrn() >= 120 && s.getPrn() <= 138)) {
                                dataStarBean.add(new DataSearchStarBean(s.getPrn(), "GPS", snr, countnumber + ""));
                            } else if (s.getPrn() >= 201 && s.getPrn() <= 261) {
                                dataStarBean.add(new DataSearchStarBean(s.getPrn(), "BEIDOU", snr, countnumber + ""));
                            } else if (s.getPrn() >= 65 && s.getPrn() <= 88) {
                                dataStarBean.add(new DataSearchStarBean(s.getPrn(), "Glonass", snr, countnumber + ""));
                            } else if (s.getPrn() >= 301 && s.getPrn() <= 336) {
                                dataStarBean.add(new DataSearchStarBean(s.getPrn(), "Galileo", snr, countnumber + ""));
                            }
                        }
                    }
                    if (bSnr) {
                        for (int i = 0; i < dataStarBean.size(); i++) {
                            dataStarBean1.add(new DataSearchStarBean(dataStarBean.get(i).getName1(), dataStarBean.get(i).getName2(), dataStarBean.get(i).getName3(), countnumber + ""));
                        }
                        bSnr = false;
                    }
                    smartTableSatellite.setData(dataStarBean1);
                    break;
                default:
                    break;
            }
        }
    };

    private void getExcelTTFF(String excelFileName) {
        String filePath = Environment.getExternalStorageDirectory().getPath()+"/GPSTestFile";
        File files = new File(filePath);
        if (!files.exists()) {
            if (files.mkdirs()) {

            } else {
                Toast.makeText(GpsTtffActivity.this, "创建失败", Toast.LENGTH_LONG).show();
                return;
            }
        }
        String[] title = {"次数", "经度", "纬度", "高度","TTFF", "TTFF-68%", "TTFF-95%", "CEP", "CEP-68%","状态","是否"};
        String resultPath = files.getAbsolutePath() + "/" + excelFileName;
        Log.e("rultPath", resultPath);
        ExcelUtil.initExcel(resultPath, title);
        File moudleFile = ExcelUtil.writeObjListToExcel(dataTestBeanList, resultPath, GpsTtffActivity.this, "TTFF");
        if (moudleFile != null) {
            Toast.makeText(GpsTtffActivity.this, "保存到本地"+resultPath, Toast.LENGTH_LONG).show();
        }
    }

    private void getExcelSatellite(String excelFileName) {
        String filePath = Environment.getExternalStorageDirectory().getPath()+"/GPSTestFile";
        File files = new File(filePath);
        if (!files.exists()) {
            if (files.mkdirs()) {

            } else {
                Toast.makeText(GpsTtffActivity.this, "创建失败", Toast.LENGTH_LONG).show();
                return;
            }
        }
        String[] title = {"卫星编码", "卫星类型", "卫星信号", "次数"};
        String resultPath = files.getAbsolutePath() + "/" + excelFileName;
        Log.e("rultPath", resultPath);
        ExcelUtil.initExcel(resultPath, title);
        File moudleFile = ExcelUtil.writeObjListToExcel(dataStarBean1, resultPath, GpsTtffActivity.this, "STAR");
        if (moudleFile != null) {
            Toast.makeText(GpsTtffActivity.this, "保存到本地"+resultPath, Toast.LENGTH_LONG).show();
        }
    }


    private void updateTTFFAndCEPS(int count) {
        double[] ttffArr = new double[count];
        double sumTTFF = 0.0d;
        double[] cepArr = new double[count];
        double sumCEP = 0.0d;
        for (int i = 0; i < count; i++) {
            ttffArr[i] = dataList.get(i).getName7();
            sumTTFF += ttffArr[i];
            cepArr[i] = dataList.get(i).getName5();
            sumCEP += cepArr[i];
        }
//        double aveTTFF = sumTTFF / ((double) count);
//        double aveCEP = sumCEP / ((double) count);
        Arrays.sort(ttffArr);
        Arrays.sort(cepArr);
        int index68 = (int) Math.ceil(0.68d * ((double) count));
        int index95 = (int) Math.ceil(0.95d * ((double) count));
        int indexCEP68 = (int) Math.ceil(0.68d * ((double) count));
        int indexCEP95 = (int) Math.ceil(0.95d * ((double) count));
        dataTestBeanList.add(new DataTestBean(countnumber, latitude + "", longitude + "", altitude+"",cepArr[indexCEP68 - 1], cepArr[indexCEP95 - 1], TTFF, ttffArr[index68 - 1], ttffArr[index95 - 1], status, "成功"));
        smartTableTtff.setData(dataTestBeanList);
    }


    private void clearDataList() {
        faileNum=0;
        countnumber=0;
        runTimes=0;
        tvPositioningFailed.setText(faileNum+"");
        tvRuntimes.setText("");
        dataList.clear();
        dataTestBeanList.clear();
        smartTableTtff.setData(dataTestBeanList);
        dataStarBean1.clear();
    }

    private Bundle getBundle() {
        Bundle bundle = new Bundle();
        if (this.mParametersPkg.warmTime) {
            bundle.putBoolean(GPSConst.GPS_CMD_TIME, true);
        }
        if (this.mParametersPkg.warmPosition) {
            bundle.putBoolean(GPSConst.GPS_CMD_POSITION, true);
        }
        if (this.mParametersPkg.warmEphemeris) {
            bundle.putBoolean(GPSConst.GPS_CMD_EPHEMERIS, true);
        }
        if (this.mParametersPkg.warmAlmanac) {
            bundle.putBoolean(GPSConst.GPS_CMD_ALMANAC, true);
        }
        if (this.mParametersPkg.warmLono_uts) {
            bundle.putBoolean(GPSConst.GPS_CMD_LONO_UTC, true);
        }
        if (this.mParametersPkg.warmHealth) {
            bundle.putBoolean(GPSConst.GPS_CMD_HEALTH, true);
        }
        if (this.mParametersPkg.warmDgps) {
            bundle.putBoolean(GPSConst.GPS_CMD_DGPS, true);
        }
        if (this.mParametersPkg.warmStr) {
            bundle.putBoolean(GPSConst.GPS_CMD_STR, true);
        }
        return bundle;
    }

    public void getInitialValue() {
        this.mParametersPkg.testTime = GPSSharedPreference.getPreference((Context) this, GPSConst.KEY_TEST_TIME, this.mParametersPkg.testTime);
        this.mParametersPkg.updatePeriod = GPSSharedPreference.getPreference((Context) this, GPSConst.KEY_UPDATE_PERIOD, this.mParametersPkg.updatePeriod);
        this.mParametersPkg.timeSpan = GPSSharedPreference.getPreference((Context) this, GPSConst.KEY_TIME_SPAN, this.mParametersPkg.timeSpan);
        this.mParametersPkg.ttff = GPSSharedPreference.getPreference((Context) this, GPSConst.KEY_TTFF, this.mParametersPkg.ttff);
        this.mParametersPkg.fixTime = GPSSharedPreference.getPreference((Context) this, GPSConst.KEY_FIX_TIME, this.mParametersPkg.fixTime);
        this.mParametersPkg.trueLatitude = Double.valueOf(GPSSharedPreference.getPreference((Context) this, GPSConst.KEY_TRUE_LATITUDE, String.valueOf(this.mParametersPkg.trueLatitude))).doubleValue();
        this.mParametersPkg.trueLongitude = Double.valueOf(GPSSharedPreference.getPreference((Context) this, GPSConst.KEY_TRUE_LONGITUDE, String.valueOf(this.mParametersPkg.trueLongitude))).doubleValue();
        this.mParametersPkg.precisionLimit = Double.valueOf(GPSSharedPreference.getPreference((Context) this, GPSConst.KEY_PRECISION_LIMIT, String.valueOf(this.mParametersPkg.precisionLimit))).doubleValue();
        this.mParametersPkg.fixPolicy = GPSSharedPreference.getPreference((Context) this, GPSConst.KEY_POLICY, this.mParametersPkg.fixPolicy);
        this.mParametersPkg.fixMode = GPSSharedPreference.getPreference((Context) this, GPSConst.KEY_MODE, this.mParametersPkg.fixMode);
        this.mParametersPkg.fixWay = GPSSharedPreference.getPreference((Context) this, GPSConst.KEY_WAY, this.mParametersPkg.fixWay);
        this.mParametersPkg.warmTime = GPSSharedPreference.getPreference((Context) this, GPSConst.KEY_WARM_TIME, Boolean.valueOf(this.mParametersPkg.warmTime));
        this.mParametersPkg.warmPosition = GPSSharedPreference.getPreference((Context) this, GPSConst.KEY_WARM_POSITION, Boolean.valueOf(this.mParametersPkg.warmPosition));
        this.mParametersPkg.warmEphemeris = GPSSharedPreference.getPreference((Context) this, GPSConst.KEY_WARM_EPHEMERIS, Boolean.valueOf(this.mParametersPkg.warmEphemeris));
        this.mParametersPkg.warmAlmanac = GPSSharedPreference.getPreference((Context) this, GPSConst.KEY_WARM_ALMANAC, Boolean.valueOf(this.mParametersPkg.warmAlmanac));
        this.mParametersPkg.warmLono_uts = GPSSharedPreference.getPreference((Context) this, GPSConst.KEY_WARM_LONO_UTS, Boolean.valueOf(this.mParametersPkg.warmLono_uts));
        this.mParametersPkg.warmHealth = GPSSharedPreference.getPreference((Context) this, GPSConst.KEY_WARM_HEALTH, Boolean.valueOf(this.mParametersPkg.warmHealth));
        this.mParametersPkg.warmDgps = GPSSharedPreference.getPreference((Context) this, GPSConst.KEY_WARM_DGPS, Boolean.valueOf(this.mParametersPkg.warmDgps));
        this.mParametersPkg.warmStr = GPSSharedPreference.getPreference((Context) this, GPSConst.KEY_WARM_STR, Boolean.valueOf(this.mParametersPkg.warmStr));
    }

    @Override
    protected void onStop() {
        super.onStop();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        stopGPSListener();
    }
}
